package org.moonlight.jvm.rtda.exclusive;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.moonlight.jvm.rtda.share.Object;
import org.moonlight.jvm.rtda.share.heap.Slots;

/**
 * 运行时数据区 - 线程独占区 - 线程 - 虚拟机栈 - 栈帧 - 局部变量表
 *
 * 局部变量表是按索引访问的，所以可以使用数组来实现。
 * 根据Java虚拟机规范，这个数组的每个元素至少可以容纳一个int或引用值，两个连续的元素可以容纳一个long或double值。
 *
 * @author Moonlight
 * @createTime 2023/8/16 10:43
 **/
@EqualsAndHashCode
public class LocalVars {

    @Getter
    private Slot[] slots;

    public LocalVars(int maxLocals) {
        if (maxLocals > 0) {
            slots = new Slot[maxLocals];
            for (int i = 0; i < maxLocals; i++) {
                slots[i] = new Slot();
            }
        }
    }

    public void setInt(int idx, int val) {
        this.slots[idx].setNum(val);
    }

    public int getInt(int idx) {
        return this.slots[idx].getNum().intValue();
    }

    public void setFloat(int idx, float val) {
        this.slots[idx].setNum(val);
    }

    public float getFloat(int idx) {
        return this.slots[idx].getNum().floatValue();
    }

    public void setLong(int idx, long val) {
        this.slots[idx].setNum(val);
    }

    public long getLong(int idx) {
        return this.slots[idx].getNum().longValue();
    }

    public void setDouble(int idx, double val) {
        this.slots[idx].setNum(val);
    }

    public double getDouble(int idx) {
        return this.slots[idx].getNum().doubleValue();
    }

    public void setRef(int idx, Object ref) {
        this.slots[idx].setRef(ref);
    }

    public Object getRef(int idx) {
        return this.slots[idx].getRef();
    }

    public void setSlot(int idx, Slot slot) { this.slots[idx] = slot; }

    public Slot getSlot(int idx) {
        return this.slots[idx];
    }

    public Object getThis() {
        return this.slots[0].getRef();
    }

    public boolean getBoolean(int idx) {
        return getInt(idx) == 1;
    }

    public static void main(String[] args) {
        LocalVars vars = new LocalVars(10);
        vars.setInt(0, 12);
        vars.setDouble(2, 3.1415d);
        vars.setFloat(4, 7.7f);
        vars.setLong(6, 111111L);

        vars.setRef(8, null);

        System.out.println(vars.getInt(0));
        System.out.println(vars.getDouble(2));
        System.out.println(vars.getFloat(4));
        System.out.println(vars.getLong(6));
        System.out.println(vars.getRef(8));
    }
}
